package com.clippick;

import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Pattern;

import org.json.JSONArray;
import org.json.JSONObject;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.StrictMode;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import co.kr.clippick.R;

import com.clippick.api.ClipPickListener;
import com.clippick.api.GetApi;
import com.clippick.clipboard.PollingThread;
import com.clippick.common.GlobalValue;
import com.clippick.common.Toasts;
import com.clippick.common.Utils;
import com.clippick.network.SocketIOClient;
import com.clippick.ui.MultiDirectionSlidingDrawer;
import com.clippick.walkthrough.HtmlPageAdapter;

public class LoginActivity extends Activity {
	// common
	private Context mContext;
	private ConnectivityManager manager;

	// data:info
	private SharedPreferences pref;
	private SharedPreferences.Editor editor;
	private SocketIOClient client;

	// view
	private MultiDirectionSlidingDrawer loginDrawer, joinDrawer;
	private EditText joinName1Text, joinName2Text, joinEmailText, joinPassText;
	private EditText userIdText, userPassText;
	private Button loginButton, joinButton, termsUrlButton;
	private CheckBox termCheckBox;
	private ProgressDialog mProgress;
	private TextView forgotPasswordText;

	// walk through
	private ImageView image1, image2, image3, image4, image5, image6, image7,
			image8;
	private int[] imageIds = { R.id.through1, R.id.through2, R.id.through3,
			R.id.through4, R.id.through5, R.id.through6, R.id.through7,
			R.id.through8 };
	private ImageView[] indicators = { image1, image2, image3, image4, image5,
			image6, image7, image8 };
	private String pagePath = "file:///android_asset/";
	private String[] pages = { "Page1.html", "Page2.html", "Page3.html",
			"Page4.html", "Page5.html", "Page6.html", "Page7.html",
			"Page8.html" };
	private String[] pagesKor = { "KPage1.html", "KPage2.html", "KPage3.html",
			"KPage4.html", "KPage5.html", "KPage6.html", "KPage7.html",
			"KPage8.html" };

	// info :login
	private String userId = "";
	private String userPass = "";

	// info :join
	private String userIdJoin = "";
	private String userPassJoin = "";
	private String userName1Join = "";
	private String userName2Join = "";

	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.login);
		mContext = this;

		if (Utils.isAndroidLowerThanICS()) {
			// remove title
			requestWindowFeature(Window.FEATURE_NO_TITLE);
		} else {
			// StrictMode.ThreadPolicy policy = new
			// StrictMode.ThreadPolicy.Builder()
			// .permitAll().build();
			// StrictMode.setThreadPolicy(policy);
		}

		pref = mContext.getSharedPreferences(GlobalValue.KEY,
				Context.MODE_PRIVATE);
		editor = mContext.getSharedPreferences(GlobalValue.KEY,
				Context.MODE_PRIVATE).edit();

		// get instance network connectivity
		manager = (ConnectivityManager) mContext
				.getSystemService(Context.CONNECTIVITY_SERVICE);

		// find view :login
		loginDrawer = (MultiDirectionSlidingDrawer) findViewById(R.id.login_drawer);
		userIdText = (EditText) findViewById(R.id.email);
		userPassText = (EditText) findViewById(R.id.user_pass);
		loginButton = (Button) findViewById(R.id.login_button);

		// set action on Password EditText :login
		userPassText
				.setOnEditorActionListener(new TextView.OnEditorActionListener() {
					@Override
					public boolean onEditorAction(TextView v, int actionId,
							KeyEvent event) {
						// TODO Auto-generated method stub
						if (actionId == EditorInfo.IME_ACTION_GO) {
							userId = userIdText.getText().toString();
							userPass = userPassText.getText().toString();
							if (!userId.equals("") && !userPass.equals("")) {
								if (Utils.checkNetwokState(manager)) {
									new LoginTask().execute();
								} else {
									Toasts.showToast(mContext,
											getString(R.string.network_fail));
								}
							}
						}

						return true;
					}
				});

		// set action :login
		loginButton.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				userId = userIdText.getText().toString();
				userPass = userPassText.getText().toString();
				if (!userId.equals("") && !userPass.equals("")) {
					if (Utils.checkNetwokState(manager)) {
						new LoginTask().execute();
					} else {
						Toasts.showToast(mContext,
								getString(R.string.network_fail));
					}
				}
			}
		});

		// find view :join
		joinDrawer = (MultiDirectionSlidingDrawer) findViewById(R.id.join_drawer);
		joinName1Text = (EditText) findViewById(R.id.name_first);
		joinName2Text = (EditText) findViewById(R.id.name_last);
		joinEmailText = (EditText) findViewById(R.id.email_join);
		joinPassText = (EditText) findViewById(R.id.user_pass_join);
		joinButton = (Button) findViewById(R.id.join_button);
		termsUrlButton = (Button) findViewById(R.id.terms_url);
		termCheckBox = (CheckBox) findViewById(R.id.terms);
		termCheckBox.setChecked(true);
		forgotPasswordText = (TextView) findViewById(R.id.forgot_password);
		forgotPasswordText.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				Intent intent = new Intent(mContext,
						ForgotPasswordActivity.class);
				startActivity(intent);
			}
		});

		// set action :join
		joinButton.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				userIdJoin = joinEmailText.getText().toString();
				userPassJoin = joinPassText.getText().toString();
				userName1Join = joinName1Text.getText().toString();
				userName2Join = joinName2Text.getText().toString();

				if (!userIdJoin.equals("") && !userPassJoin.equals("")
						&& !userName1Join.equals("")
						&& !userName2Join.equals("")
						&& termCheckBox.isChecked()) {
					if (checkEmail(userIdJoin)) {
						if (Utils.checkNetwokState(manager)) {
							new JoinTask().execute();
						} else {
							Toasts.showToast(mContext,
									getString(R.string.network_fail));
						}
					}
				} else {
					Toasts.showToast(mContext,
							getString(R.string.join_fail_with_blank));
				}
			}
		});

		// set action: join process
		joinPassText
				.setOnEditorActionListener(new TextView.OnEditorActionListener() {
					@Override
					public boolean onEditorAction(TextView v, int actionId,
							KeyEvent event) {
						// TODO Auto-generated method stub
						if (actionId == EditorInfo.IME_ACTION_GO) {
							userIdJoin = joinEmailText.getText().toString();
							userPassJoin = joinPassText.getText().toString();
							userName1Join = joinName1Text.getText().toString();
							userName2Join = joinName2Text.getText().toString();

							if (!userIdJoin.equals("")
									&& !userPassJoin.equals("")
									&& !userName1Join.equals("")
									&& !userName2Join.equals("")
									&& termCheckBox.isChecked()) {
								if (checkEmail(userIdJoin)) {
									if (Utils.checkNetwokState(manager)) {
										new JoinTask().execute();
									} else {
										Toasts.showToast(
												mContext,
												getString(R.string.network_fail));
									}
								}
							} else {
								Toasts.showToast(
										mContext,
										getString(R.string.join_fail_with_blank));
							}
							return true;
						}

						return false;
					}
				});

		termsUrlButton.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				Uri uri = Uri.parse("http://clippick.com/new_terms.html");
				Intent intent = new Intent(Intent.ACTION_VIEW, uri);
				startActivity(intent);
			}
		});

		// set pager: walk through
		ViewPager pager = (ViewPager) findViewById(R.id.pager);
		pager.setAdapter(new HtmlPageAdapter(mContext, getWalkThroughList()));
		pager.setOnPageChangeListener(new MyPageChangeListener());

		// hide walk through views for login
		pager.setVisibility(View.GONE);
		LinearLayout indicatorLayer = (LinearLayout) findViewById(R.id.linear1);
		indicatorLayer.setVisibility(View.GONE);

		if (!isOurUser()) {
			showWalkThroughActivity();
		}
	}

	private boolean isOurUser() {
		return pref.getBoolean("walk", false);
	}

	private void showWalkThroughActivity() {
		Intent intent = new Intent(mContext, WalkThroughActivity.class);
		startActivity(intent);
	}

	private List<String> getWalkThroughList() {
		// system language
		String language = Locale.getDefault().getDisplayLanguage();

		List<String> pageList = new ArrayList<String>();
		for (int i = 0; i < pages.length; i++) {
			if (language.equals("한국어")) {
				pageList.add(pagePath + pagesKor[i]);
			} else {
				pageList.add(pagePath + pages[i]);
			}
			indicators[i] = (ImageView) findViewById(imageIds[i]);
		}
		indicators[0].setImageResource(R.drawable.indicator_high);

		return pageList;
	}

	// check email type
	private boolean checkEmail(String email) {
		return EMAIL_ADDRESS_PATTERN.matcher(email).matches();
	}

	// HTTP Task from Thread
	class JoinTask extends AsyncTask<String, String, String> {
		ProgressDialog mProgress;
		String result = "";

		protected void onPreExecute() {
			mProgress = new ProgressDialog(mContext);
			mProgress.setMessage("Loading");
			mProgress.show();
		}

		@Override
		protected String doInBackground(String... params) {
			GetApi api = new GetApi(mContext);
			// return Y or N
			result = api.joinApi(userIdJoin, userPassJoin, userName1Join,
					userName2Join);
			Log.i("join", result);

			return null;
		}

		protected void onPostExecute(String unused) {
			mProgress.dismiss();
			if (result.contains("Y")) {
				// show alert
				Toasts.showToast(mContext, getString(R.string.join_success));

				// animate
				// joinDrawer.animateClose();
				// loginDrawer.animateOpen();

				// remove edittext
				joinName1Text.setText("");
				joinName2Text.setText("");
				joinEmailText.setText("");
				joinPassText.setText("");

				// start login directly
				userId = userIdJoin;
				userPass = userPassJoin;
				new LoginTask().execute();
			} else {
				// show alert
				Toasts.showToast(mContext, getString(R.string.join_fail));
			}
		}
	}

	// HTTP Request from thread
	class LoginTask extends AsyncTask<String, String, String> {
		int returnCode = 0;
		String returnMessage = null;
		Map<String, String> response = null;

		protected void onPreExecute() {
			mProgress = new ProgressDialog(mContext);
			mProgress.setMessage("Loading");
			mProgress.setCancelable(false);
			mProgress.show();

			hideKeyboard(userIdText);
			hideKeyboard(userPassText);
		}

		@Override
		protected String doInBackground(String... params) {
			GetApi api = new GetApi(mContext);
			response = api.loginApi(userId, userPass);
			Log.i("login", response.toString());
			returnCode = Integer.parseInt(response.get("returnCode"));

			if (returnCode != 200) {
				returnMessage = response.get("returnMessage");
			}

			return null;
		}

		protected void onPostExecute(String unused) {
			switch (returnCode) {
			case 200:
				// store user data
				pref.edit().putString("REGISTRATION_KEY",
						response.get("REGISTRATION_KEY").toString());
				editor.putString("UserID", userId);
				editor.putString("PW", userPass);
				editor.commit();

				// store as global variable to access easier
				GlobalValue.USER_ID = userId;
				GlobalValue.USER_KEY = pref.getString("REGISTRATION_KEY", "");
				GlobalValue.UPDATE_TIME = response.get("UPDATE_TIME")
						.toString();
				GlobalValue.AppLatestSyncTime = GlobalValue.UPDATE_TIME;
				// GlobalValue.setUpdateTime(mContext,
				// GlobalValue.AppLatestSyncTime);
				GlobalValue.IS_FIRST_LOGIN_USER = true;

				// try to connect with socket.io
				// if (ClipPickListener.SOCKET_COUNT <= 0)
				// connectSocketIO();
				// else {
				mProgress.dismiss();
				Log.d("login", "already connected with socket.IO");
				startClipPick();
				// }
				break;

			default:
				// show message why failed logging in
				mProgress.dismiss();
				Toasts.showToast(mContext, returnMessage);
				break;
			}
		}
	}

	private void hideKeyboard(EditText editText) {
		InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
		imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
	}

	private void connectSocketIO() {
		ClipPickListener.socketMessage = new ClipPickListener.ClipPickOnMessage() {
			@Override
			public void onMessage(String event, JSONArray arguments) {
				// TODO Auto-generated method stub

				Log.d("login", event + ":" + arguments);

				if (event.toString().contains("giveme")) {
					ClipPickListener.sendSocketMessage(userId);
				} else if (event.toString().contains("received")) {
					ClipPickListener.SOCKET_COUNT++;
					mProgress.dismiss();
					startClipPick();
				} else if (event.contains("newevent")) {
					try {
						Log.i("login", "this is new event");
						JSONArray array = new JSONArray(arguments.toString());
						JSONObject data = array.getJSONObject(0);
						JSONArray result = data.getJSONArray("data");

						// checkLocalDbSync(GetPolling.convertArrayWithJSON(result));

						Log.d("login", "convertedArrayWithJSON : "
								+ PollingThread.convertArrayWithJSON(result));

						// send it to ClipMonitorServce.class to compare with
						// local database
						Intent intent = new Intent();
						intent.putExtra("feed", PollingThread
								.convertArrayWithJSON(result).toString());
						intent.setAction("com.clippick.newsyncfeeds");
						sendBroadcast(intent);

					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}

			@Override
			public void onError(Exception error) {
				Log.d("login", error + "");
				ClipPickListener.SOCKET_COUNT--;
			}

			@Override
			public void onDisConnect(int code, String reason) {
				Log.d("login", reason);
				ClipPickListener.SOCKET_COUNT--;
			}

			@Override
			public void onConnect() {
				Log.d("login", "connected!");
			}
		};

		ClipPickListener.client = new SocketIOClient(
				URI.create("http://clippick.com:8124"),
				ClipPickListener.listener);
		ClipPickListener.client.connect();
	}

	private void startClipPick() {
		mProgress.dismiss();
		// save initial user info
		editor.putString("userPass", userPass);
		editor.putString("userID", userId);
		editor.putBoolean("autoSync", true);
		editor.putBoolean("autoLaunch", true);
		editor.commit();

		// start clippick
		Intent intent = new Intent(mContext, MainActivity.class);
		startActivity(intent);
		this.overridePendingTransition(R.anim.bottom_to_top,
				R.anim.top_to_bottom);
		finish();
	}

	public final Pattern EMAIL_ADDRESS_PATTERN = Pattern
			.compile("[a-zA-Z0-9\\+\\.\\_\\%\\-\\+]{1,256}" + "\\@"
					+ "[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}" + "(" + "\\."
					+ "[a-zA-Z0-9][a-zA-Z0-9\\-]{0,25}" + ")+");

	// return when pager changes its view
	private class MyPageChangeListener extends
			ViewPager.SimpleOnPageChangeListener {
		@Override
		public void onPageSelected(int position) {
			// set image by position
			for (int i = 0; i < indicators.length; i++) {
				if (i == position) {
					indicators[i].setImageResource(R.drawable.indicator_high);
				} else {
					indicators[i].setImageResource(R.drawable.indicator_low);
				}

			}
		}
	}
}
